﻿// <copyright file="CongressMemberBioAndRole.cs" company="Microsoft Corporation">
// Copyright (c) 2009 Microsoft Corporation All Rights Reserved
// </copyright>
// <author>Michael S. Scherotter</author>
// <email>mischero@microsoft.com</email>
// <date>2009-05-21</date>
// <summary>CongressMemberBioAndRole class definition</summary>

namespace NYTimes
{
    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Globalization;
    using System.Linq;
    using System.Xml.Linq;
    using NYTimes.Core;
    using NYTimes.Data;

    /// <summary>
    /// New York Times US Congress member roles and bio API
    /// </summary>
    public class CongressMemberBioAndRole : Core.CongressApi
    {
        #region Fields
        /// <summary>
        /// the member ID
        /// </summary>
        private string memberId;

        #endregion

        /// <summary>
        /// Initializes a new instance of the CongressMemberBioAndRole class.
        /// </summary>
        public CongressMemberBioAndRole()
        {
            this.Roles = new ObservableCollection<CongressMemberRole>();

            if (SampleData.IsInDesignTool)
            {
                var xml = Core.SampleData.GetSampleData("CongressMemberBioAndRoles.xml");

                if (!string.IsNullOrEmpty(xml))
                {
                    this.ParseXml(xml);
                }
            }
        }

        #region Properties

        /// <summary>
        /// Gets or sets the member's unique ID number
        /// </summary>
        [Description("Gets or sets the member's unique ID number")]
        public string MemberId
        {
            get
            {
                return this.memberId;
            }

            set
            {
                if (this.memberId != value)
                {
                    this.memberId = value;

                    this.FetchResults();
                }
            }
        }

        /// <summary>
        /// Gets the bio and role for a member of congress
        /// </summary>
        public CongressMember Bio { get; private set; }

        /// <summary>
        /// Gets the roles for a member of congress
        /// </summary>
        public ObservableCollection<CongressMemberRole> Roles { get; private set; }
        #endregion

        /// <summary>
        /// determines whether the state is valid to fetch results
        /// </summary>
        /// <returns>true if the MemberId is not null or empty</returns>
        public override bool ShouldFetchResults()
        {
            return !string.IsNullOrEmpty(this.MemberId);
        }

        /// <summary>
        /// Generate the service URL
        /// </summary>
        /// <param name="baseUri">the base URI</param>
        /// <returns>the REST URL</returns>
        public override Uri GenerateUrl(string baseUri)
        {
            var uriString = string.Format(CultureInfo.InvariantCulture, "{0}/members/{1}.xml?api-key={2}", baseUri, this.MemberId, this.ApiKey);

            return new Uri(uriString, UriKind.Absolute);
        }

        /// <summary>
        /// Clear the Roles
        /// </summary>
        public override void ClearResults()
        {
            this.Roles.Clear();
        }

        /// <summary>
        /// parse the XML results from the web service
        /// </summary>
        /// <param name="results">the XML results</param>
        public override void OnParseResults(XElement results)
        {
            if (results == null)
            {
                throw new ArgumentNullException("results");
            }

            var member = results.Element("member");

            this.Bio = new CongressMember()
            {
                CSpanId = member.Element("cspan_id").Value,
                DateOfBirth = DateTime.Parse(member.Element("date_of_birth").Value, CultureInfo.InvariantCulture),
                FirstName = member.Element("first_name").Value,
                Gender = member.Element("gender").Value,
                GovTrackId = member.Element("govtrack_id").Value,
                Id = member.Element("id").Value,
                LastName = member.Element("last_name").Value,
                MiddleName = member.Element("middle_name").Value,
                Name = member.Element("name") == null ? null : member.Element("name").Value,
                Url = string.IsNullOrEmpty(member.Element("url").Value) ? null : new Uri(member.Element("url").Value, UriKind.Absolute)
            };

            this.TriggerPropertyChanged("Bio");

            var roles = from role in member.Element("roles").Elements("role")
                        select new CongressMemberRole()
                        {
                            Chamber = role.Element("chamber").Value,
                            Committees = role.Element("committees") == null ? null : from committee in role.Element("committees").Elements("committee")
                                         select new Committee()
                                         {
                                             BeginDate = DateTime.Parse(committee.Element("begin_date").Value, CultureInfo.InvariantCulture),
                                             Code = committee.Element("code").Value,
                                             EndDate = DateTime.Parse(committee.Element("end_date").Value, CultureInfo.InvariantCulture),
                                             Name = committee.Element("name").Value,
                                             RankInParty = int.Parse(committee.Element("rank_in_party").Value, CultureInfo.InvariantCulture)
                                         },
                            Congress = int.Parse(role.Element("congress").Value, CultureInfo.InvariantCulture),
                            District = string.IsNullOrEmpty(role.Element("district").Value) ? new int?() : int.Parse(role.Element("district").Value, CultureInfo.InvariantCulture),
                            EndDate = DateTime.Parse(role.Element("end_date").Value, CultureInfo.InvariantCulture),
                            MissedVotePercent = (role.Element("missed_votes_pct") == null) ? new float?() : float.Parse(role.Element("missed_votes_pct").Value, CultureInfo.InvariantCulture),
                            Party = role.Element("party").Value,
                            StartDate = DateTime.Parse(role.Element("start_date").Value, CultureInfo.InvariantCulture),
                            State = role.Element("state").Value,
                            Title = role.Element("title").Value,
                            VotesWithPartyPercent = (role.Element("votes_with_party_pct") == null) ? new float?() : float.Parse(role.Element("votes_with_party_pct").Value, CultureInfo.InvariantCulture)
                        };

            foreach (var role in roles)
            {
                this.Roles.Add(role);
            }
        }
    }
}
